﻿/*
 
CCCCCC  H    H  L      OOOOOO  EEEEE
C       H    H  L      O    O  E
C       H HH H  L      O    O  EEEE
C       H    H  L      O    O  E
CCCCCC  H    H  LLLLL  OOOOOO  EEEEE

*/

/*
 * Chloe.ORM documentation：http://www.52chloe.com/Wiki/Document
 */

using Ace;
using Chloe;
using Chloe.Infrastructure.Interception;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Loader;
using System.Text;
using System.Threading.Tasks;

namespace Ace.Data
{
    public delegate IDbContext CreateDbContextHandle();
    public class DbContextFactory
    {
        public static string ConnectionString { get; private set; }
        public static string DbType { get; private set; }
        public static string SpaceFileName { get; private set; }
        static DbContextFactory()
        {
            ConnectionString = Globals.Configuration["db:ConnString"];
          

            string dbType = Globals.Configuration["db:DbType"];
            var SpaceDllName = Globals.Configuration["db:SpaceDllName"];
            var baseurl = AppDomain.CurrentDomain.BaseDirectory;
            var fn = Path.Combine(baseurl, SpaceDllName);
            if (!File.Exists(fn))
            {
                fn = Path.Combine(baseurl, "lib", SpaceDllName);
                if (!File.Exists(fn))
                {
                    fn = Path.Combine(baseurl, "bin", SpaceDllName);
                    if (!File.Exists(fn))
                        throw new Exception("can't find context space dll file ,filename=" + fn);
                }
            }
            SpaceFileName = fn;
            if (string.IsNullOrEmpty(dbType) == false)
                DbType = dbType.ToLower();

            string dbintercptor= Globals.Configuration["db:CanIntercepte"];
            bool canInterceptor = false;
            bool.TryParse(dbintercptor, out canInterceptor);
            if (canInterceptor)
            {
                IDbCommandInterceptor interceptor = new DbCommandInterceptor();
                DbInterception.Add(interceptor);
            }
        }
        
        public static IDbContext CreateContext()
        {
            IDbContext dbContext = CreateContext(ConnectionString);
            return dbContext;
        }
        public static IDbContext CreateContext(string connString)
        {
            IDbContext dbContext = null;

            if (DbType == "sqlite")
            {
                dbContext = CreateSQLiteContext(connString);
            }
            else if (DbType == "sqlserver")
            {
                dbContext = CreateSqlServerContext(connString);
            }
            else if (DbType == "mysql")
            {
                dbContext = CreateMySqlContext(connString);
            }
            else if (DbType == "oracle")
            {
                dbContext = CreateOracleContext(connString);
            }
            else
            {
                dbContext = CreateSqlServerContext(connString);
            }

            return dbContext;
        }

        static IDbContext CreateSqlServerContext(string connString)
        {
            
            var myAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(SpaceFileName);
            var myType = myAssembly.GetType("Chloe.SqlServer.MsSqlContext");
            var dbContext = Activator.CreateInstance(myType,new string[] { ConnectionString}) as IDbContext;
            
            return dbContext;
        }
        static IDbContext CreateMySqlContext(string connString)
        {
            var myAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(SpaceFileName);
            var myType = myAssembly.GetType("Chloe.Mysql.MySqlContext");
            var dbContext = Activator.CreateInstance(myType, new string[] { ConnectionString }) as IDbContext;
            return dbContext;
        }
        static IDbContext CreateOracleContext(string connString)
        {
            var myAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(SpaceFileName);
            var myType = myAssembly.GetType("Chloe.Oracle.OracleContext");
            var dbContext = Activator.CreateInstance(myType, new string[] { ConnectionString }) as IDbContext;
            return dbContext;
        }
        static IDbContext CreateSQLiteContext(string connString)
        {
            var myAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(SpaceFileName);
            var myType = myAssembly.GetType("Chloe.SQLite.SQLiteContext");
            var dbContext = Activator.CreateInstance(myType, new string[] { ConnectionString }) as IDbContext;

             return dbContext;
        }
    }
}
